package com.google.code.securityflow.cfg

import com.google.code.securityflow.ast.{Operator, SourceLocation}

abstract class Node {
  def id: Int;

  def location: SourceLocation;

  def canonicalName: String;
}

abstract class ConstantNode(id: Int, location: SourceLocation) extends Node {

}

case class OutNode(id: Int, valueVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "Out[value: v" + valueVar + "]";
}

case class BinaryOperatorNode(id: Int, operator: Operator, left: Int, right: Int, resultVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "Binary[" + operator.canonicalName + ", left: v" + left + ", right: v" + right + ", result: " + resultVar + "]";
}

case class CallNode(id: Int, valueVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "Call[value: v" + valueVar + "]";
}

case class IfNode(id: Int, valueVar: Int, joinBlock: BasicBlock, location: SourceLocation) extends Node {
  def canonicalName = "If[value: v" + valueVar + "]";
}

case class IntegerLiteralNode(id: Int, value: Int, resultVar: Int, high: Boolean, location: SourceLocation) extends ConstantNode(id, location) {
  def canonicalName = "IntegerLiteral['" + value + "', result: v" + resultVar + "]";
}

case class ObjectLiteralNode(id: Int, resultVar: Int, location: SourceLocation) extends ConstantNode(id, location) {
  def canonicalName = "ObjectLiteral[result: v" + resultVar + "]";
}

case class FunctionLiteralNode(id: Int, function: Function, resultVar: Int, location: SourceLocation) extends ConstantNode(id, location) {
  def canonicalName = "FunctionLiteral[result: v" + resultVar + "]";
}

case class NoOpNode(id: Int, location: SourceLocation) extends Node {
  def canonicalName = "NoOp[]";
}

case class ReadVariableNode(id: Int, name: String, resultVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "ReadVariableNode['" + name + "', result: v" + resultVar + "]";
}

case class ReadPropertyNode(id: Int, name: String, baseVar: Int, resultVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "ReadProperty['" + name + "', base: v" + baseVar + ", result: v" + resultVar + "]";
}

case class WriteVariableNode(id: Int, name: String, valueVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "WriteVariableNode['" + name + "', value: v" + valueVar + "]";
}

case class WritePropertyNode(id: Int, name: String, baseVar: Int, valueVar: Int, location: SourceLocation) extends Node {
  def canonicalName = "WriteProperty['" + name + "', base: v" + baseVar + ", value: v" + valueVar + "]";
}
